package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import model.HCalc;
import model.HCalcResults;
import view.MainScreen;

public class Controller {
	
	private MainScreen view;
	private HCalc model;
	private boolean isSimulating;
	
	
	public Controller(HCalc model, MainScreen view){
		this.view = view;
		this.model = model;
		
		view.setCalculateBtnListener(new CalculateListener());
		view.setSimulate_n_Listener(new Simulate_n_Listener());
		view.setSimulate_k_Listener(new Simulate_k_Listener());
	}
	
	
	private JFreeChart createJFreeChart(HCalcResults results){
		XYSeries series = new XYSeries("Hypergeometric Distribution");
		 
		 for(Point2D.Double p: results.getResults()){
			 series.add(p.getX(), p.getY());
		 }
		 
		 // Add the series to your data set
		 XYSeriesCollection dataset = new XYSeriesCollection();
		 dataset.addSeries(series);
		 	 
		//Generate graph
		JFreeChart chart = ChartFactory.createHistogram(
					 "Hypergeometric Distribution",
		            HCalcResults.x_LABEL, 
		            HCalcResults.h_LABEL, 
		            dataset,
		            PlotOrientation.VERTICAL,
		            true,
		            true,
		            false
			        );
		
		
		 return chart;
	}
	
	private JFreeChart createJFreeChartWithIncreasing_n(ArrayList<HCalcResults> results){
		
		
		XYSeries series = new XYSeries("Simulation as n increases");
		
		for(HCalcResults result: results){
			series.add(result.get_n(), result.getTotalProb());
		}
		
		// Add the series to your data set
		XYSeriesCollection dataset = new XYSeriesCollection();
		dataset.addSeries(series);
	
		//Generate graph
		JFreeChart chart = ChartFactory.createHistogram(
					 "Simulation as n increases",
			            HCalcResults.n_LABEL, 
			            HCalcResults.h_LABEL, 
			            dataset,
			            PlotOrientation.VERTICAL,
			            true,
			            true,
			            false
			        );
	
		  
		 return chart;
	}
	
	private JFreeChart createJFreeChartWithIncreasing_k(ArrayList<HCalcResults> results){
		XYSeries series = new XYSeries("Simulation as k increases");
		
		for(HCalcResults result: results){
			series.add(result.get_k(), result.getTotalProb());
		}
		
		// Add the series to your data set
		XYSeriesCollection dataset = new XYSeriesCollection();
		dataset.addSeries(series);
		
		//Generate graph
		JFreeChart chart = ChartFactory.createHistogram(
					 "Simulation as k increases",
			            HCalcResults.k_LABEL, 
			            HCalcResults.h_LABEL, 
			            dataset,
			            PlotOrientation.VERTICAL,
			            true,
			            true,
			            false
			        );
		
		 return chart;
	}
	
	class CalculateListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent arg0) {
	
			try{
				if(!isSimulating && view.isInputValid(MainScreen.CALCULATE_MODE)){
					HCalcResults results = HCalc.calculateProbFromRange(view.get_XRange(), view.get_N(), view.get_n(), view.get_k());
					
					view.setTableContent(results);
					view.setGraphContent(createJFreeChart(results));
					System.out.println(results.getResults().get(0).getY());
				}
				else{
					if(isSimulating)
						view.displayError("Please wait for simulation to finish.");
					else
						view.displayError(view.getErrorMsg(MainScreen.CALCULATE_MODE));
				}
			}catch(Exception e){e.printStackTrace();}
		}
	}
	
	class Simulate_n_Listener implements ActionListener{

		Thread thread;
	
		@Override
		public void actionPerformed(ActionEvent arg0) {
			if((thread == null || !thread.isAlive()) && !isSimulating){
				isSimulating = true;
				thread = new Thread(new Simulate_n_Thread());
				thread.start();
			}
		}
	}
	
	class Simulate_k_Listener implements ActionListener{

		Thread thread;
	
		@Override
		public void actionPerformed(ActionEvent arg0) {
		
			if((thread == null || !thread.isAlive()) && !isSimulating){
				isSimulating = true;
				thread = new Thread(new Simulate_k_Thread());
				thread.start();
			}
		}
	}
	
	class Simulate_n_Thread implements Runnable{

		@Override
		public void run() {
			int coolDown = 100; //ms
			long start = System.currentTimeMillis();
			ArrayList<HCalcResults> resultList = new ArrayList<HCalcResults>();
			if(view.isInputValid(MainScreen.SIMULATE_n_MODE)){
				try{
					Point2D.Double x = view.get_XRange();
					int N = view.get_N();
					int k = view.get_k();
					int i = (int)x.getY();
					while(i <= N){
						if(System.currentTimeMillis() - start >= coolDown ){
							HCalcResults results = HCalc.calculateProbFromRange(x, N, i, k);
							resultList.add(results);
							view.setGraphContent(createJFreeChartWithIncreasing_n(resultList));
							start = System.currentTimeMillis();
							i++;
						}
					}
				}catch(Exception e){e.printStackTrace();}
			}
			else
				view.displayError(view.getErrorMsg(MainScreen.SIMULATE_n_MODE));
			
			isSimulating = false;
		}
	}
	
	class Simulate_k_Thread implements Runnable{

		@Override
		public void run() {
			int coolDown = 100; //ms
			long start = System.currentTimeMillis();
			ArrayList<HCalcResults> resultList = new ArrayList<HCalcResults>();
			if(view.isInputValid(MainScreen.SIMULATE_k_MODE)){
				try{
					Point2D.Double x = view.get_XRange();
					int N = view.get_N();
					int n = view.get_n();
					int i = (int)x.getY();
					while(i <= N){
						if(System.currentTimeMillis() - start >= coolDown ){
							HCalcResults results = HCalc.calculateProbFromRange(x, N, n, i);
							resultList.add(results);
							view.setGraphContent(createJFreeChartWithIncreasing_k(resultList));
							start = System.currentTimeMillis();
							i++;
						}
					}
				}catch(Exception e){e.printStackTrace();}
			}
			else
				view.displayError(view.getErrorMsg(MainScreen.SIMULATE_k_MODE));
			
			isSimulating = false;
		}
	}
}
